/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.composite.editpart;

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.XYLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.RequestConstants;
import org.eclipse.gef.tools.CellEditorLocator;
import org.eclipse.gef.tools.DirectEditManager;
import org.eclipse.uml2.uml.AggregationKind;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Property;

import com.cea.papyrus.core.directedit.ILabelControler;
import com.cea.papyrus.core.directedit.LabelCellEditorLocator;
import com.cea.papyrus.core.directedit.LabelControler;
import com.cea.papyrus.core.directedit.LabelDirectEditManager;
import com.cea.papyrus.core.directedit.PropertyAccessor;
import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.editpart.ContainerHighlightEditPolicy;
import com.cea.papyrus.core.editpart.ContainerWithSemanticEditPart;
import com.cea.papyrus.core.figures.IconFigure;
import com.cea.papyrus.core.helper.ModelerHelper;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagram.composite.figure.ClassFigure;
import com.cea.papyrus.diagraminterchange2.di2.Di2Factory;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;
import com.cea.papyrus.umlutils.ICustomAppearence;

/**
 * Controler for {@link Property} edit parts in composite diagrams.
 */
public class PropertyEditPart extends ContainerWithSemanticEditPart {

	/** Manager for property name edition */
	private DirectEditManager manager;

	/**
	 * Creates a new PropertyEditPart.
	 * @param graphNode the graph node representing the property
	 * @param modelManager the model manager associated to the editor
	 */
	public PropertyEditPart(GraphNode graphNode, ModelManager modelManager) {
		super(graphNode, modelManager);
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.ContainerWithSemanticEditPart#createEditPolicies()
	 */
	@Override
	protected void createEditPolicies() {
		super.createEditPolicies();
        // overload the GRAPHICAL_NODE_ROLE editPolicy to use the diagram specific one
        installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE, new GraphNodeEditPolicy() );

        installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE,
				new ContainerHighlightEditPolicy());// Does not run?!!
		if(getContentPane() != null) {
			installEditPolicy(EditPolicy.LAYOUT_ROLE, new CompositeLayoutEditPolicy(
					(XYLayout) getContentPane().getLayoutManager()));
		}
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.GraphNodeWithSemanticEditPart#createFigure()
	 */
	@Override
	protected IFigure createFigure() {
		// Force initialization of the manager when figure has changed
		manager = null;	
		//  Try to get figure from ContainerWithSemanticEditPart
		IFigure fig = super.createFigure();
		if (fig != null) {
			return fig;
		}
		return new ClassFigure();
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.GraphNodeWithSemanticEditPart#getUmlElement()
	 */
	@Override
	public org.eclipse.uml2.uml.Property getUmlElement() {
		Element e=((Uml1SemanticModelBridge)getGraphNode().getSemanticModel()).getElement();

		// case of element import
		if(e instanceof ElementImport){
			return (org.eclipse.uml2.uml.Property)((ElementImport) e).getImportedElement();
		}
		// this is a simple Property
		return (org.eclipse.uml2.uml.Property)e;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.GraphNodeWithSemanticEditPart#refreshVisuals()
	 */
	@Override
	protected void refreshVisuals() {

		Dimension size = getGraphNode().getSize();
		Point p = getGraphNode().getPosition();
		Rectangle r = new Rectangle(p, size);

		IFigure fig = getFigure();

		//  if fig is a stereotype figure
		if (!(fig instanceof ClassFigure)) {
			IconFigure icf= (IconFigure)getFigure();
			icf.setName(((NamedElement)getUmlElement()).getName());

		} else {
			ClassFigure f = (ClassFigure)fig;

			// refresh name
			com.cea.papyrus.umlutils.Property utilProperty = new com.cea.papyrus.umlutils.Property(this.getUmlElement());

			int style = ICustomAppearence.DEFAULT_UML_COMPO_PROPERTY;
			// get properties on graph node for property: custom display
			String value = getProperty(ICustomAppearence.CUSTOM_APPEARENCE_KEY);

			if(value == null) {
				com.cea.papyrus.diagraminterchange2.di2.Property prop = Di2Factory.eINSTANCE.createProperty();
				getGraphNode().getProperty().add(prop);
				prop.setKey(ICustomAppearence.CUSTOM_APPEARENCE_KEY);
				value = ""+ICustomAppearence.DEFAULT_UML_COMPO_PROPERTY;
				prop.setValue(value);
			}
			if(value != null) {
				try {
					style = Integer.parseInt(value);
				} catch (NumberFormatException e) {
					Debug.log(e);
				}
			}

			String newText = utilProperty.getCustomLabel(style);

			f.setName(newText);

			// set colors
			f.refreshColors(getGraphNode());

			// look for list of stereotypes
			String stereotypePresentation = null;
			if(getGraphNode().getSemanticModel() != null) {
				if(getGraphNode().getSemanticModel().getPresentation() != null) {
					stereotypePresentation = getGraphNode().getSemanticModel().getPresentation();
				} else {
					getGraphNode().getSemanticModel().setPresentation(ModelerHelper.TEXT_STEREOTYPE_PRESENTATION);
					stereotypePresentation = ModelerHelper.TEXT_STEREOTYPE_PRESENTATION;
				}
			}
			// Retrieve current class and figure
			org.eclipse.uml2.uml.Property currentProperty = getUmlElement();
			com.cea.papyrus.umlutils.Element currentElement = new com.cea.papyrus.umlutils.Element(getUmlElement());

			f.refreshPresentation(getPresentation(), currentProperty, getGraphNode());
			boolean hasIcon  = currentElement.hasIcon();
			boolean hasShape = currentElement.hasShape();

			f.refreshStereotypes(f.stereotypesLabel(this), getPresentation(), hasIcon, hasShape);
			
			if (getUmlElement().getAggregation().equals(AggregationKind.COMPOSITE_LITERAL)){
				f.setExtern(false);
			} else {
				f.setExtern(true);
			}
		}
		if(getParent() != null) {
			((GraphicalEditPart) getParent()).setLayoutConstraint(this, fig, r);
		}
		

	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#getContentPane()
	 */
	@Override
	public IFigure getContentPane() {
		IFigure fig = getFigure();
		if(fig instanceof ClassFigure) {
			return ((ClassFigure)fig).getContentsPane();
		}
		return null;
	}

	/**
	 * Returns the Name Label of this edit part.
	 * @return the label for this figure that displays the name of the element
	 */
	protected Label getNameLabel() {
		IFigure fig = getFigure();

		if (fig instanceof IconFigure) {
			return (Label) fig;
		} else if (fig instanceof ClassFigure) {
			return ((ClassFigure) fig).getNameLabel();
		} else {
			Debug.error(this, "CompositePropertyEditPart::getNameLabel() : Unknown Figure type.", channel);
			return null;
		}
	}

	/**
	 * the direct edit mechanism requires the edit part to handle the direct
	 * edit request. This method determines which label the user clicked on. The
	 * label is passed to the ConditionessionCellEditorLocator which positions
	 * the cell editor over the selected label.
	 * @param req the direct edit request to perform
	 */
	public void performDirectEdit(Request req) {
		initLabelEditManager();
		manager.show();
	}

	/**
	 * Init the label direct edit manager.
	 * This method should be called when a Direct Edit request is performed.
	 */
	protected void initLabelEditManager() {
		if(manager==null) {
			// locator for the cell editor (on the name label)
			CellEditorLocator locator = new LabelCellEditorLocator(getNameLabel());

			// defining how properties are modified in the model
			PropertyAccessor accessor = new PropertyAccessor() {
				/* (non-Javadoc)
				 * @see com.cea.papyrus.common.directedit.PropertyAccessor#getPropertyName()
				 */
				@Override
				public String getPropertyName() {
					return "Name";
				}

				/* (non-Javadoc)
				 * @see com.cea.papyrus.common.directedit.PropertyAccessor#getValue()
				 */
				public String getValue() {
					return getUmlElement().getName();
				}
				/* (non-Javadoc)
				 * @see com.cea.papyrus.common.directedit.PropertyAccessor#setValue(java.lang.String)
				 */
				public void setValue(String value) {
					getUmlElement().setName(value);  
				}
			};
			// defines the controler: link between model and view
			ILabelControler labelControler = new LabelControler(getNameLabel(), accessor);

			// creates the editing manager.
			manager = new LabelDirectEditManager(this, locator, labelControler);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.gef.editparts.AbstractEditPart#performRequest(org.eclipse.gef.Request)
	 */
	@Override
	public void performRequest(Request request){
		if (RequestConstants.REQ_DIRECT_EDIT.equals(request.getType())) {
			performDirectEdit(request);
		}
	}
}
